package ar.com.jendrix.common.persistence.manager;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.log4j.Logger;

import ar.com.jendrix.common.exception.ApplicationException;
import ar.com.jendrix.common.exception.SystemException;
import ar.com.jendrix.common.persistence.entity.BaseEntity;
import ar.com.jendrix.common.util.Comparator;

public abstract class BaseEntityDAO<BE extends BaseEntity> implements EntityDAO<BE>, IdentifyEntity<BE> {

	protected Logger log = Logger.getLogger(getClass());

	/**
	 * 
	 * @return
	 */
	protected abstract EntityManager getEntityManager();

	/**
	 * 
	 * @param entityID
	 * @return
	 * @throws SystemException
	 */
	@Override
	public final BE get(Long entityId) throws SystemException {
		BE entity = null;
		try {
			entity = getEntityManager().find(getEntityClass(), entityId);
		} catch (Throwable t) {
			throw new SystemException(t);
		}
		return entity;
	}

	/**
	 * 
	 * @param entityId
	 * @return
	 * @throws SystemException
	 */
	@Override
	public final BE getFull(Long entityID) throws SystemException {
		BE entity = null;
		try {
			entity = get(entityID);
			if (entity != null) {
				entity.initLazyElements();
			}
		} catch (Throwable t) {
			throw new SystemException(t);
		}
		return entity;
	}

	@SuppressWarnings("unchecked")
	@Override
	public final List<BE> getList() throws SystemException {
		List<BE> entityList = null;
		try {

			StringBuilder hql = new StringBuilder();
			hql.append("select e ");
			hql.append("from " + getEntityClass().getSimpleName() + " e ");
			hql.append("order by e.id asc");

			Query query = getEntityManager().createQuery(hql.toString());
			entityList = query.getResultList();

		} catch (Throwable t) {
			throw new SystemException(t);
		}
		return entityList;
	}

	/**
	 * 
	 * @param entity
	 * @return
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	@Override
	public BE save(BE entity) throws ApplicationException, SystemException {
		BE newEntity = null;
		try {
			// Saves data.
			if (Comparator.isEmpty(entity.getId())) {
				newEntity = entity;
				getEntityManager().persist(newEntity);
			} else {
				newEntity = getEntityManager().merge(entity);
			}
		} catch (Throwable t) {
			throw new SystemException(t);
		}
		return newEntity;
	}

	/**
	 * 
	 * @param entityId
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	@Override
	public void delete(Long entityId) throws ApplicationException, SystemException {
		try {
			BE entity = get(entityId);

			if (entity != null) {
				getEntityManager().remove(entity);
			}
		} catch (Throwable t) {
			throw new SystemException(t);
		}
	}

	/**
	 * 
	 * @param entityId
	 * @throws ApplicationException
	 * @throws SystemException
	 */
	@Override
	public void logicalDelete(Long entityId) throws ApplicationException, SystemException {
		throw new ApplicationException("LogicalDelete no implemendato!");
	}
}